﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using D2DEngine.Scene;
using Microsoft.Xna.Framework;
using D2DEngine.Core;
using D2DEngine.Physics;

namespace D2DEngine.Tile
{
    public class D2DTileMap : D2DSceneObject
    {
        protected int width;
        protected int height;       

        protected D2DTileSet tileSet;

        protected List<D2DTileLayer> layers = new List<D2DTileLayer>();
        protected D2DCollisionLayer collisionLayer = null;
        protected D2DMonsterLayer monsterLayer = null;


        /// <summary>
        /// The tile set of the map
        /// </summary>
        public D2DTileSet TileSet
        {
            get { return this.tileSet; }
            set { this.tileSet = value; }
        }        

        /// <summary>
        /// The list of layers in the map
        /// </summary>
        public List<D2DTileLayer> Layers
        {
            get { return this.layers; }
        }

        /// <summary>
        /// The map's width in pixels
        /// </summary>
        public int WidthInPixels
        {
            get { return this.width * tileSet.TileSize; }
        }

        /// <summary>
        /// The map's height in pixels
        /// </summary>
        public int HeightInPixels
        {
            get { return this.height * tileSet.TileSize; }
        }

        /// <summary>
        /// The width of the map in cells
        /// </summary>
        public int Width
        {
            get { return this.width; }
            set { this.width = value; }
        }

        /// <summary>
        /// The height of the map in cells
        /// </summary>
        public int Height
        {
            get { return this.height; }
            set { this.height = value; }
        }

        /// <summary>
        /// The collision layer of the map
        /// </summary>
        public D2DCollisionLayer CollisionLayer
        {
            get { return this.collisionLayer; }
            set { this.collisionLayer = value; }
        }

        /// <summary>
        /// The collision layer of the map
        /// </summary>
        public D2DMonsterLayer MonsterLayer
        {
            get { return this.monsterLayer; }
            set { this.monsterLayer = value; }
        }


        public D2DTileMap()
        {
        }        


        /// <summary>
        /// Converts a Vector2 position into a Point (cell) 
        /// </summary>
        /// <param name="position">The position</param>
        /// <returns>Point representing the cell</returns>
        public Point PositionToCell(Vector2 position)
        {
            return new Point(
                (int)Math.Round(position.X / (float)this.tileSet.TileSize),
                (int)Math.Round(position.Y / (float)this.tileSet.TileSize));
        }

        /// <summary>
        /// Converts a map cell into a world position
        /// </summary>
        /// <param name="x">The X coordinate of the cell</param>
        /// <param name="y">The Y coordinate of the cell</param>
        /// <returns>Vector2 corresponding to the world position</returns>
        public Vector2 CellToPosition(int x, int y)
        {
            return new Vector2((float)(x * this.tileSet.TileSize), (float)(y * this.tileSet.TileSize));
        }

        /// <summary>
        /// Draws the map
        /// </summary>
        /// <param name="spriteBatch"></param>
        public override void Draw(SpriteBatch spriteBatch)
        {
            if (this.visible)
            {
                // Calculate the minimum and maximum cells of the map to display
                D2DCamera camera = this.scene.Camera;

                Point min = PositionToCell(camera.Position - new Vector2(this.tileSet.TileSize, this.tileSet.TileSize));
                Point max = PositionToCell(
                    camera.Position + new Vector2(D2DSettings.ScreenWidth + this.tileSet.TileSize, D2DSettings.ScreenHeight + this.tileSet.TileSize));

                foreach (D2DTileLayer layer in this.layers)
                {
                    layer.Draw(spriteBatch, this.tileSet, min, max);
                }

                base.Draw(spriteBatch);
            }
        } 

    }
}
